package com.project.zsxd.server.authentication;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.project.zsxd.server.common.helper.ContextBeanHelper;
import com.project.zsxd.server.common.util.ConstantUtil;
import com.project.zsxd.server.common.util.JWTUtil;
import com.project.zsxd.server.user.entity.User;
import com.project.zsxd.server.user.service.IUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List;

/**
 * Created by kaler on 2020/5/16.
 */
public class MyRealm extends AuthorizingRealm {

    private IUserService userService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    /**
     * 获取用户权限信息
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = JWTUtil.getUserInfo(principalCollection.toString());
        User user = userService.getById(userName);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        if (null != user) {
            //查询用户拥有的角色和权限信息
            List<String> roleIds = userService.queryRolesByUserName(userName);
            simpleAuthorizationInfo.setRoles(new HashSet<>(roleIds));
            List<String> permissionIds = userService.queryPermissionsByUserName(userName);
            simpleAuthorizationInfo.setStringPermissions(new HashSet<>(permissionIds));
        }
        return simpleAuthorizationInfo;
    }

    /**
     * 用户认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (null == userService) {
            userService = ContextBeanHelper.getBean(IUserService.class);
        }
        String token = (String) authenticationToken.getCredentials();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        if (ConstantUtil.LOGIN_PASS_URLS.contains(request.getRequestURI())) {
            request.setAttribute("currentUser",new User());
            return new SimpleAuthenticationInfo(token, token, this.getName());
        }

        String userName = JWTUtil.getUserInfo(token);
        if (userName == null) {
            throw new AuthenticationException("token invalid");
        }
        User user = userService.getById(userName);
        if (user == null) {
            throw new AuthenticationException("User didn't existed!");
        }

        try {
            JWTUtil.verify(token, userName, user.getPasswd());
        } catch (TokenExpiredException e) {
            // token过期时，重新获取新的token返回
            String newToken = JWTUtil.sign(userName, user.getPasswd());
            throw new TokenExpiredException(newToken);
        }

        return new SimpleAuthenticationInfo(user, token, this.getName());
    }
}
